iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 24
0

上一篇做了一些更動,包含 貼文路由需驗證 及 Post 關聯到 User

但不小心破壞到原本寫好的程式了,讓我們來看看是什麼問題。

  • 關於 如何使用範例程式碼,請參考 TDD 實戰 D1
    • 本篇版本包含:5d

錯誤訊息

首先來查看,執行 PHPUnit 時跳出了什麼錯誤訊息。

Post (Tests\Feature\Post)
 ✔ All post
 ✔ Insert post
 ✘ Insert post by get route
   ┐
   ├ Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: posts.user_id (SQL: insert into "posts" ("post_text", "user_id", "updated_at", "created_at") values (It's a new post., ?, 2019-10-08 13:18:19, 2019-10-08 13:18:19))

可以知道是 Insert post by get route 這個測試,並且發現 NOT NULL constraint failed: posts.user_id,判斷是因為新增資料時,Not null 的欄位沒有資料。

修正 Insert post by get route

有時候出現錯誤,我們要修正的是 Bug 的來源。

但這裡的情況是,我們程式的邏輯已經改變:新增貼文需要已登入,並抓取 user.id 放到 posts 的 user_id 中。

原本用來貼文的 GET 路由,我們已經不再需要它,因此我們直接刪掉那段程式與測試就可以了 [1]。

// routes/web.php

// Route::get('/post/insert', 'PostController@insertPost');
// tests/Feature/PostTest.php

// public function testInsertPostByGetRoute()
// {
//     ...
// }

修正 Insert post by post route

Post 方法的新增貼文,我們要繼續留著用,因此來修改測試。

重構

類似的情況,POST 路由的控制器其實已經是寫好的程式碼,因此比較像是重構。

    public function testInsertPostByPostRoute()
    {
        $users = factory(User::class, 2)->create();
        $second_user = $users[1];
        
        $text = "It's a new post.";

        $this->actingAs($second_user)
             ->post('/post',[
                'post_text' => $text
        ]);

        $this->assertDatabaseHas('posts', [
            'post_text' => $text,
            'user_id' => $second_user->id
        ]);

        $response = $this->get('/post');
        $response->assertSee($text);
    }

( $ git checkout 5d )

相對於 Dusk 的 LoginAs(),Laravel 支援 actingAs() 來登入特定使用者。

完成!

我們目前有兩種測試:PHPUnit 與 Dusk:

$ php artisan dusk
PHPUnit 8.3.5 by Sebastian Bergmann and contributors.

....                                                                4 / 4 (100%)

Time: 6.86 seconds, Memory: 26.00 MB

OK (4 tests, 5 assertions)

$ ./vendor/bin/phpunit
PHPUnit 8.3.5 by Sebastian Bergmann and contributors.

....                                                                4 / 4 (100%)

Time: 535 ms, Memory: 26.00 MB

OK (4 tests, 7 assertions)

終於回到了測試全部通過的狀態,感覺不錯。


Regression Test (回歸測試)

再次介紹一下 Regression Test,我們曾在 TDD 的理由 中提到過。

它的用途是當我們有了一個新版本的程式,或甚至每一次對程式碼的任何更動後,我們去執行一次自動化測試,確保原有的程式並沒有被破壞。

由於自動化測試很快就能執行完,幾乎不需要等待,讓開發者更願意隨時進行 regression test。

而上一篇的實作後,能夠那麼快發現有 Bug,以及在本篇中找到是從哪裡發生的,也就是仰賴了自動化測試與 regression test,我們有很高的機會能透過它們抓到剛出現的錯誤。


附註

  1. TDD 並沒有規範如何刪掉不需要的程式,我目前採取先刪除產品程式,後刪除測試的順序。如果要更保險一點,也可以寫測試去確認原功能已不能使用。

上一篇
TDD 實戰 D9:Laravel 關聯式資料庫
下一篇
TDD 實戰 D11:Laravel 修改貼文顯示
系列文
如何一步步實踐TDD (測試驅動開發)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言